﻿using System;
using System.IO;
using System.Net;
using System.Text;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.IO.Compression;
using System.Collections;

namespace QQForm
{
    /// <summary>
        /// HTTP/HTTPS资源的请求。
        /// </summary>
        public class QQHttpRequest
        {
            /// <summary>
            /// 保持Cookie为同一Cookie值。
            /// </summary>    
            protected CookieContainer __Cookie__ = new CookieContainer();
            /// <summary>
            /// 保持Cookie为同一Cookie值。
            /// </summary>
            public CookieContainer Cookie
            {
                get
                {
                    return __Cookie__;
                }
                set
                {
                    __Cookie__ = value;
                }
            }
            /// <summary>
            /// 标识 Internet 资源的 URI
            /// </summary>    
            protected string __Uri__ = "";
            /// <summary>
            /// 读取的网址
            /// </summary>
            public Uri RequestUri
            {
                get
                {
                    return new Uri(__Uri__);
                }
            }
            /// <summary>
            /// 标识 Internet 资源请求的 Referer  
            /// </summary>    
            public string Referer = "";
            /// <summary>
            /// 标识 Internet 资源请求的 Header
            /// </summary>    
            public Hashtable Headers = new Hashtable();
            /// <summary>
            /// 标识 Internet 资源请求的 Accept
            /// </summary>    
            public string Accept = @"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*";
            public string UserAgent = @"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; EmbeddedWB 14.52 from: http://www.bsalsa.com/ EmbeddedWB 14.52; .NET CLR 2.0.50727; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
            private string __Method__ = "GET";
            /// <summary>
            /// 标识 Internet 资源请求的 Method
            /// </summary>    
            /// <summary>
            /// 访问地址的方法
            /// </summary>
            public string Method
            {
                get
                {
                    return __Method__;
                }
            }
            /// <summary>
            /// POST请求时的数据
            /// </summary>    
            private string __Data__ = null;
            /// <summary>
            /// 发送的数据
            /// </summary>
            public string PostDate
            {
                get
                {
                    return __Data__;
                }
            }
            /// <summary>
            ///  响应的字符集
            /// </summary>    
            public string CharacterSet = "gb2312";
            /// <summary>
            /// 响应状态
            /// </summary>    
            protected HttpStatusCode __StatusCode__;
            /// <summary>
            /// 返回读取地址状态值
            /// </summary>
            public HttpStatusCode StatusCode
            {
                get
                {
                    return __StatusCode__;
                }
            }
            /// <summary>
            /// 错误响应状态
            /// </summary>
            protected WebExceptionStatus _ExceptionStatus_;
            /// <summary>
            /// 返回的错误代码
            /// </summary>
            public WebExceptionStatus ExceptionStatus
            {
                get
                {
                    return _ExceptionStatus_;
                }
            }
            /// <summary>
            /// 标识 Internet 资源请求的 Accept
            /// </summary>    
            protected StringBuilder __Html_Text__ = new StringBuilder();
            /// <summary>
            /// 读取的网页内容
            /// </summary>
            public string HtmlDocument
            {
                get
                {
                    return __Html_Text__.ToString();
                }
            }
            public Image newimg
            {
                get { return _newimg; }
            }
            protected Image _newimg;


            protected byte[] _ReadStream;
            /// <summary>
            /// 返回读取的流对像
            /// </summary>
            public byte[] ReadStream
            {
                get
                {
                    return _ReadStream;
                }
            }
            /// <summary>
            /// 连接超时
            /// </summary>
            public int Timeout = 10000;
            protected string __StrCookie__ = "";
            /// <summary>
            /// 设置string Cookie。
            /// </summary>
            public string StrCookie
            {
                get
                {
                    if (__Uri__.Length > 0)
                    {
                        CookieCollection cc = __Cookie__.GetCookies(RequestUri);
                        string Str = "";
                        for (int i = 0; i < cc.Count; i++)
                        {
                            Str = Str + cc[i].Name + "=" + cc[i].Value + ";";
                        }
                        return Str;
                    }
                    else
                    {
                        return __StrCookie__;
                    }
                }
                set
                {
                    __StrCookie__ = value;
                }
            }
            /// <summary>
            /// 设置StrCookie
            /// </summary>
            protected void SetStrCookie()
            {
                string[] ck = __StrCookie__.Split(';');
                Uri _uri = RequestUri;
                //CookieCollection cookieCollection = new CookieCollection();
                //string[] ck = Regex.Split(__StrCookie__, ";", RegexOptions.IgnoreCase);

                //foreach (string i in ck) { string[] ss = Regex.Split(i.Trim(), "=", RegexOptions.IgnoreCase); cookieCollection.Add(new Cookie(ss[0].ToString().Trim(), Regex.Replace(ss[1].ToString().Trim(),",","\",\""))); } //__Cookie__.SetCookies(_uri, i.Trim()); ;
                //__Cookie__.Add(_uri, cookieCollection);
                for (int i = 0; i < ck.Length; i++)
                {
                    //__Cookie__.SetCookies(_uri, Regex.Replace(ck[i].Trim(),",","\t"));
                    __Cookie__.Add(_uri, new Cookie("",""));
                }
            }
            /// <summary>
            /// 允许自动跳转
            /// </summary>
            public bool AllowAutoRedirect = true;
            /// <summary>
            /// 类初始化
            /// </summary>
            public QQHttpRequest()
            {
                //
                // TODO: 在此处添加构造函数逻辑
                //
            }

            /// <summary>
            /// 对 Internet 资源发起GET请求
            /// </summary>
            /// <param name="Url">要访问的地址</param>
            /// <param name="Referer">导入该地址的页面</param>
            /// <returns>是否成功</returns>
            public bool OpenRequest(string Url, string Referer)
            {
                return OpenRequest(Url, Referer, "", "GET");
            }

            /// <summary>
            /// 对 Internet 资源发起GET请求
            /// </summary>
            /// <param name="Url">要访问的地址</param>
            /// <param name="Referer">导入该地址的页面</param>
            /// <param name="PostData">要发送的数据</param>
            /// <returns>是否成功</returns>
            public bool OpenRequest(string Url, string Referer, string PostData)
            {
                if (PostData != null)
                {
                    return OpenRequest(Url, Referer, PostData, "POST");
                }
                else
                {
                    return OpenRequest(Url, Referer, "", "GET");
                }
            }

            private bool OpenRequest(string _url, string _Referer, string _PostData, string _Method)
            {
                //保存参数
                __Uri__ = _url;
                Referer = _Referer;
                __Data__ = _PostData;
                __Method__ = _Method;

                // 清空已保留代码
                __Html_Text__.Remove(0, __Html_Text__.Length);

                // 创建 HttpWebRequest 实例
                HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(__Uri__);

                // 设置跟随重定向
                Request.AllowAutoRedirect = false;

                #region 判断Uri资源类型
                {
                    Regex __RegexUri_ = new Regex("^https://", RegexOptions.IgnoreCase);
                    if (__RegexUri_.IsMatch(__Uri__))
                        ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
                }
                #endregion

                Request.Timeout = this.Timeout;
                Request.Method = __Method__;
                Request.Accept = Accept;
                Request.UserAgent = UserAgent;// "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)";
                Request.Referer = Referer;
                Request.Method = Method;
                Request.Headers.Add("Accept-Encoding:gzip, deflate");
                Request.Headers.Add("Cache-Control:no-cache");
                Request.Headers.Add("Accept-Language:zh-cn");
                Request.KeepAlive = true;
                Request.ServicePoint.Expect100Continue = false;
                //SetStrCookie();
                //Request.CookieContainer = __Cookie__;

                if (Method == "POST")
                {
                    #region 请求为POST
                    Request.ContentType = "application/x-www-form-urlencoded";
                    byte[] Bytes = Encoding.GetEncoding(CharacterSet).GetBytes("Cookie: "+__StrCookie__ + "\r\n\r\n" + __Data__);
                    Request.ContentLength = Bytes.Length;
                    using (Stream writer = Request.GetRequestStream())
                    {
                        writer.Seek(-2, SeekOrigin.End);
                        writer.Write(Bytes, 0, 176);
                        writer.Close();
                    }
                    #endregion
                }

                #region 读取返回数据
                // 设置返回值变量
                try
                {
                    HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
                   
                    // 获取状态值
                    __StatusCode__ = Response.StatusCode;

                    switch (__StatusCode__)
                    {
                        case HttpStatusCode.Found:
                            try
                            {
                                if (AllowAutoRedirect)
                                {
                                    try
                                    {
                                        string NewLocalation = GetUrl(_url, Response.Headers["Location"]);
                                        Response.Close();
                                        return OpenRequest(NewLocalation, _url, "", "GET");
                                    }
                                    catch (Exception err)
                                    {
                                        __Html_Text__.Append(err.Message);
                                        return false;
                                    }
                                }
                                else
                                {
                                    return GetResponse(Response);
                                }

                            }
                            catch (WebException e)
                            {
                                _ExceptionStatus_ = e.Status;
                                return false;
                            }
                        case HttpStatusCode.OK:
                            // 判断页面编码
                            return GetResponse(Response);
                        default:
                            Response.Close();
                            return false;
                    }
                }
                catch (WebException e)
                {
                    _ExceptionStatus_ = e.Status;
                    __Html_Text__.Append(e.Message);
                    return false;
                }

                #endregion
            }

            private bool GetResponse(HttpWebResponse Response)
            {
                try
                {
                    
                    string ContentEncoding = Response.ContentEncoding.ToLower();
                    switch (ContentEncoding)
                    {
                        case "gzip":
                            _ReadStream = ReadStreamEx(new GZipStream(Response.GetResponseStream(), CompressionMode.Decompress));
                            break;
                        case "deflate":
                            _ReadStream = ReadStreamEx(new DeflateStream(Response.GetResponseStream(), CompressionMode.Decompress));
                            break;
                        
                        default:
                            
                            break;
                    }
                    if (Regex.IsMatch(Response.ContentType, "text", RegexOptions.IgnoreCase))
                    {
                        _ReadStream = ReadStreamEx(Response.GetResponseStream());
                        __Html_Text__.Append(Encoding.GetEncoding(CharacterSet).GetString(_ReadStream));
                        Response.Close();
                        return true;
                    }
                    if (Regex.IsMatch(Response.ContentType, "jpeg", RegexOptions.IgnoreCase))
                    {
                        
                        _newimg = System.Drawing.Image.FromStream(Response.GetResponseStream());
                        Response.Close();
                        return true;
                    }
                    _ReadStream = ReadStreamEx(Response.GetResponseStream());
                    Response.Close();
                    return true;
                }
                catch (WebException e)
                {
                    _ExceptionStatus_ = e.Status;
                    __Html_Text__.Append(e.Message);
                    return false;
                }
            }

            /// <summary>
            /// 读取流转换为比特数组
            /// </summary>
            /// <param name="reader"></param>
            /// <returns></returns>
            private static byte[] ReadStreamEx(Stream reader)
            {
                try
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        int nSize = 4096;
                        byte[] writeData = new byte[nSize];
                        while (true)
                        {
                            try
                            {
                                nSize = reader.Read(writeData, 0, nSize);
                                if (nSize > 0)
                                    ms.Write(writeData, 0, nSize);
                                else
                                    break;
                            }
                            catch
                            {
                                break;
                            }
                        }
                        reader.Close();
                        return ms.GetBuffer();
                    }
                }
                catch
                {
                    return null;
                }
            }

            /// <summary>
            /// 当 Uri 资源为 HTTPS 时，忽略证书。
            /// </summary>
            public static bool ValidateServerCertificate(
                  object sender,
                  X509Certificate certificate,
                  X509Chain chain,
                  SslPolicyErrors sslPolicyErrors)
            {
                //if (sslPolicyErrors == SslPolicyErrors.None)
                return true;
            }

            public static string GetUrl(string url, string relativUrl)
            {
                return new Uri(new Uri(url), relativUrl).AbsoluteUri;
            }

        } 


    
}
